package org.liu.simpleTank;

import java.util.EventListener;
import java.util.EventObject;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class RobotManager {
	private Game game;
	private static final int THRESHOLD = 6;
	private SpawnPoint[] spawnPoints;
	{
		spawnPoints = new SpawnPoint[3];
		for(int i = 0; i < spawnPoints.length; i++)
			spawnPoints[i] = new SpawnPoint();
	}
	
	public RobotManager(Game game) {
		this.game = game;
	}
	
	public void setSpawnPoints() {
		for(int i = 0; i < spawnPoints.length; i++) {
			spawnPoints[i].clear(); // clear spawn queue
			spawnPoints[i].addListener(spawnListener);
		}
		game.getMap().placeElement(0, 0, spawnPoints[0]);
		game.getMap().placeElement(0, 12, spawnPoints[1]);
		game.getMap().placeElement(0, 24, spawnPoints[2]);
	}
	
	// robots count
	private int tank1_count;
	private int tank2_count;
	private int tank3_count;
	private int tank_count;
	{
		tank1_count = 10;
		tank2_count = 5;
		tank3_count = 5;
		tank_count = 20;
	}
	
	public void setTankCount(int a, int b, int c) {
		tank1_count = a;
		tank2_count = b;
		tank3_count = c;
		tank_count = a + b + c;
	}
	
	private int tank_count_now;
	{
		tank_count_now = 0;
	}
	
	/**
	 * listen on tank events and count and 
	 * create new tanks
	 */
	public void initialSpawn() {
		while(tank_count_now < THRESHOLD && tank_count > 0) {
			dispatch();
		}
	}
	
	private void dispatch() {
		if(tank_count <= 0) // no tank remain, exit
			return;
		// choose a type of tank
		int type = CONSTS.NONE;
		while(type == CONSTS.NONE) {
			switch((int)(Math.random() * 3)) {
			case 0:
				if(tank1_count > 0) {
					type = CONSTS.TANK_1;
					--tank1_count;
				}
				break;
			case 1: 
				if(tank2_count > 0) {
					type = CONSTS.TANK_2;
					--tank2_count;
				}
				break;
			case 2: 
				if(tank3_count > 0) {
					type = CONSTS.TANK_3;
					--tank3_count;
				}
				break;
			default: break;
			}
		}
		--tank_count;
		++tank_count_now;
		
		// choose a spawn point
		int idx = (int)(Math.random() * 3);
		spawnPoints[idx].add(type);
	}
	
	// listeners
	private Element.ElementListener tankDestroyedListener;
	private SpawnPoint.SpawnListener spawnListener;
	{
		tankDestroyedListener = new Element.ElementListener() {
			@Override
			public void destroyed(EventObject e) {
				--tank_count_now;
				if(tank_count > 0 && tank_count_now < THRESHOLD)
					dispatch();
			}
		};
		spawnListener = new SpawnPoint.SpawnListener() {
			@Override
			public void spawn(SpawnPoint.SpawnEvent e) {
				SpawnPoint sp = (SpawnPoint)e.getSource();
				int type = e.getType();
				Tank t = game.placeTank(type, sp.row, sp.col, CONSTS.DOWN);
				if(type == CONSTS.TANK_2)
					t.setSpeed(Tank.SPEED_FAST);
				if(type == CONSTS.TANK_3)
					t.setLife(3);
				t.addElementListener(tankDestroyedListener);
				t.getStatus().setDir((int)(Math.random() * 4)); // random dir value according to CONSTS
				t.getStatus().setFire(true);
				t.addListener(new RobotAI());
			}
		};
	}
	
	public void reset() {
		tank_count_now = 0;
	}
	
	public static abstract class RobotManagerListener implements EventListener {
		public abstract void robotCleaned();
	}
	
	private List<RobotManagerListener> listeners;
	{
		listeners = new ArrayList<RobotManager.RobotManagerListener>(4);
	}
	
	public void addListener(RobotManagerListener listener) {
		listeners.add(listener);
	}
	
	public void robotCleaned() {
		Iterator<RobotManagerListener> iter = listeners.iterator();
		while(iter.hasNext()) {
			iter.next().robotCleaned();
		}
	}
}
